package com.sudo.service.admin.service.impl;

import com.github.pagehelper.PageHelper;
import com.sudo.common.task.TaskMethod;
import com.sudo.common.task.TaskParam;
import com.sudo.common.utils.PagedGridResult;
import com.sudo.dao.admin.entity.SysServerNode;
import com.sudo.dao.admin.entity.SysServerNodeTask;
import com.sudo.dao.admin.mapper.SysServerNodeTaskMapper;
import com.sudo.dao.admin.model.bo.SysServerBeanMethodBO;
import com.sudo.dao.admin.model.bo.SysServerNodeTaskBO;
import com.sudo.rpc.api.model.RegistryBean;
import com.sudo.rpc.api.model.RegistryMethod;
import com.sudo.rpc.api.model.RegistryServer;
import com.sudo.service.admin.service.AdminBaseService;
import com.sudo.service.admin.service.SysServerNodeTaskService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Service
public class SysServerNodeTaskServiceImpl extends AdminBaseService implements SysServerNodeTaskService {

    @Resource
    private SysServerNodeTaskMapper sysServerNodeTaskMapper;

    @Override
    public void deleteAndSaveServerNodeTask(String server, RegistryServer registryServer) {
        Example example = new Example(SysServerNodeTask.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo(SysServerNodeTask.Field.server, server);
        sysServerNodeTaskMapper.deleteByExample(example);

        List<RegistryBean> beanList = registryServer.getBeanList();
        if (CollectionUtils.isEmpty(beanList)) {
            return;
        }
        List<SysServerNodeTask> sysServerNodeTaskList = new ArrayList<>();
        for (RegistryBean registryBean : beanList) {
            log.info("========== 注册bean：{} ==========", registryBean.getBeanName());
            List<RegistryMethod> registryMethodList = registryBean.getRegistryMethodList();
            for (RegistryMethod registryMethod : registryMethodList) {
                SysServerNodeTask sysServerNodeTask = new SysServerNodeTask();
                sysServerNodeTask.setServer(server);
                sysServerNodeTask.setBeanName(registryBean.getBeanName());
                sysServerNodeTask.setMethodName(registryMethod.getMethodName());
                sysServerNodeTask.setMethodParams(registryMethod.getMethodParams());
                sysServerNodeTask.setMethodDesc(registryMethod.getDesc());
                sysServerNodeTaskList.add(sysServerNodeTask);
                log.info("     注册方法：{}",registryMethod.getMethodName());
            }
        }
        sysServerNodeTaskMapper.insertList(sysServerNodeTaskList);
    }

    @Override
    public Map<String, Map<String, Map<String, TaskMethod>>> getServerNodeTaskMap() {

        List<SysServerNodeTask> sysServerNodeTaskList = sysServerNodeTaskMapper.selectAll();

        return getTaskMethodParamCountMap(sysServerNodeTaskList);
    }

    @Override
    public List<TaskParam> getTaskParamList(SysServerBeanMethodBO sysServerBeanMethodBO) {
        Example example = new Example(SysServerNodeTask.class);
        example.selectProperties(SysServerNodeTask.Field.methodParams);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo(SysServerNodeTask.Field.server, sysServerBeanMethodBO.getServer());
        criteria.andEqualTo(SysServerNodeTask.Field.beanName, sysServerBeanMethodBO.getBeanName());
        criteria.andEqualTo(SysServerNodeTask.Field.methodName, sysServerBeanMethodBO.getMethodName());
        List<SysServerNodeTask> sysServerNodeTaskList = sysServerNodeTaskMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(sysServerNodeTaskList)) {
            return null;
        }
        SysServerNodeTask sysServerNodeTask = sysServerNodeTaskList.get(0);

        List<TaskParam> taskParamList = new ArrayList<>();
        String[] params = sysServerNodeTask.getMethodParams().split("\\|");
        for (String string : params) {
            if (StringUtils.isNotBlank(string)) {
                TaskParam taskParam = new TaskParam(string);
                taskParamList.add(taskParam);
            }
        }
        return taskParamList;
    }

    private static Map<String, Map<String, Map<String, TaskMethod>>> getTaskMethodParamCountMap(List<SysServerNodeTask> sysServerNodeTaskList) {
        Map<String, Map<String, Map<String, TaskMethod>>> stringMapMap = new HashMap<>();

        for (SysServerNodeTask sysServerNodeTask : sysServerNodeTaskList) {
            Map<String, Map<String, TaskMethod>> beanNameMap = stringMapMap.computeIfAbsent(sysServerNodeTask.getServer(), k -> new HashMap<>());
            Map<String, TaskMethod> methodNameMap = beanNameMap.computeIfAbsent(sysServerNodeTask.getBeanName(), k -> new HashMap<>());
            TaskMethod taskMethod = new TaskMethod();
            taskMethod.setMethodName(sysServerNodeTask.getMethodName());
            taskMethod.setMethodDesc(sysServerNodeTask.getMethodDesc());

            List<TaskParam> taskParamList = new ArrayList<>();
            String[] params = sysServerNodeTask.getMethodParams().split("\\|");
            for (String string : params) {
                if (StringUtils.isNotBlank(string)) {
                    TaskParam taskParam = new TaskParam(string);
                    taskParamList.add(taskParam);
                }
            }
            taskMethod.setTaskParamList(taskParamList);
            methodNameMap.put(sysServerNodeTask.getMethodName(), taskMethod);
        }
        return stringMapMap;
    }

    @Override
    public SysServerNodeTask getSysServerNodeTask(String server, String beanName, String methodName) {
        Example example = new Example(SysServerNodeTask.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo(SysServerNodeTask.Field.server, server);
        criteria.andEqualTo(SysServerNodeTask.Field.beanName, beanName);
        criteria.andEqualTo(SysServerNodeTask.Field.methodName, methodName);
        return sysServerNodeTaskMapper.selectOneByExample(example);
    }

    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    @Override
    public int analysisAndSaveServerNodeTask(SysServerNode serverNode, Object data) {
        RegistryServer registryServer = (RegistryServer) data;
        List<RegistryBean> beanList = registryServer.getBeanList();
        List<SysServerNodeTask> sysServerNodeTaskList = new ArrayList<>();
        // 1.先删除历史任务
        Example example = new Example(SysServerNodeTask.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo(SysServerNodeTask.Field.server, serverNode.getServer());
        sysServerNodeTaskMapper.deleteByExample(example);

        if (CollectionUtils.isNotEmpty(beanList)) {
            for (RegistryBean registryBean : beanList) {
                List<RegistryMethod> registryMethodList = registryBean.getRegistryMethodList();
                if (CollectionUtils.isNotEmpty(registryMethodList)) {
                    for (RegistryMethod registryMethod : registryMethodList) {
                        SysServerNodeTask sysServerNodeTask = new SysServerNodeTask();
                        sysServerNodeTask.setServer(serverNode.getServer());
                        sysServerNodeTask.setBeanName(registryBean.getBeanName());
                        sysServerNodeTask.setMethodName(registryMethod.getMethodName());
                        sysServerNodeTask.setMethodParams(registryMethod.getMethodParams());
                        sysServerNodeTask.setMethodDesc(registryMethod.getDesc());
                        sysServerNodeTaskList.add(sysServerNodeTask);
                    }
                }
            }
        }
        if (CollectionUtils.isNotEmpty(sysServerNodeTaskList)) {
            return sysServerNodeTaskMapper.insertList(sysServerNodeTaskList);
        }
        return 0;
    }

    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    @Override
    public PagedGridResult querySysServerNodeTaskByPage(SysServerNodeTaskBO sysServerNodeTaskBO) {
        PageHelper.startPage(sysServerNodeTaskBO.getPage(), sysServerNodeTaskBO.getLimit());
        Example example = new Example(SysServerNodeTask.class);
        example.orderBy(SysServerNodeTask.Field.id).desc();
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(sysServerNodeTaskBO.getServer())) {
            criteria.andEqualTo(SysServerNodeTask.Field.server,sysServerNodeTaskBO.getServer());
        }
        if (StringUtils.isNotBlank(sysServerNodeTaskBO.getBeanName())) {
            criteria.andEqualTo(SysServerNodeTask.Field.beanName,sysServerNodeTaskBO.getBeanName());
        }
        if (StringUtils.isNotBlank(sysServerNodeTaskBO.getMethodName())) {
            criteria.andEqualTo(SysServerNodeTask.Field.methodName,sysServerNodeTaskBO.getMethodName());
        }
        List<SysServerNodeTask> sysServerNodeTaskList = sysServerNodeTaskMapper.selectByExample(example);
        return setterPagedGrid(sysServerNodeTaskList, sysServerNodeTaskBO.getPage());
    }
}
